package guiclient;

import javax.swing.*;
import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

public class Client implements Runnable {

    private StringSocket serverChannel;
    private String serverName;
    private int serverPort;
    private static final String DEFAULT_SERVER_NAME = "localhost";
    private static final int DEFAULT_SERVER_PORT = 2004;
    List<OrderTableBean> orderTableBeen;
    private List<String> poolCommands = new ArrayList<String>();
    private AtomicBoolean fill = new AtomicBoolean(false);

    Client(List<OrderTableBean> orderTableBeen) {
        this.orderTableBeen = orderTableBeen;
        this.serverName = DEFAULT_SERVER_NAME;
        this.serverPort = DEFAULT_SERVER_PORT;
    }

    Client(List<OrderTableBean> orderTableBeen, final String serverName, final int serverPort) {
        this.orderTableBeen = orderTableBeen;
        this.serverName = serverName;
        this.serverPort = serverPort;
    }

    public void connect() {
        try {
            serverChannel = new StringSocket(new Socket(serverName, serverPort));
        } catch (IOException e) {
            //log
        }
    }

    public void sendMessage(String message) {
        try {
            serverChannel.write(message);
        } catch (IOException e) {
            //log
        }
    }

    public String receiveMessage() {
        try {
            return serverChannel.read();
        } catch (IOException e) {
            return null; //log
        }
    }

    public int available() {
        try {
            return serverChannel.available();
        } catch (IOException e) {
            return 0;
        }
    }

    @Override
    public void run() {
        while (true) {
            while ((available() > 0)&&(fill.get())) {
                String message = receiveMessage();
                if (!ClientMessageHandler.handleServerMessage(message, orderTableBeen)) {
                    poolCommands.add(message);
                }
            }
        }
    }

    public void sendAuthMessage(String clientName) {
        ClientMessageHandler.sendMessage(MessagePrefix.AUTH + " " + clientName,
                this);
    }

    public boolean receiveAuthMessage() throws AuthClientException {
        String message = receiveMessage();
        try {
            return ClientMessageHandler.answerAuthClient(message);
        } catch (AuthClientException e) {
            poolCommands.add(message);
            throw new AuthClientException(e.getMessage());
        }
    }

    public void sendOrder(String type, String stock, String price,
                          String size) {
        ClientMessageHandler.sendMessage(type + " " + stock + " " + price + " "
                + size, this);
    }

    public long receiveOrderMessage() throws AddOrderException {
        String message = receiveMessage();
        try {
            return ClientMessageHandler.answerOrderClient(message);
        } catch (AddOrderException e) {
            poolCommands.add(message);
            throw new AddOrderException(e.getMessage());
        }
    }

    public boolean getFill() {
        return fill.get();
    }

    public void setFill(boolean fill) {
        this.fill.set(fill);
    }
}